﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Security.Cryptography;
using System.Drawing.Imaging;
using System.Drawing;
using System.Drawing.Text;

namespace CWB.Common.Utilities
{
    public class CImgVerify
    {
        #region Constructor
        /// <summary>
        /// The constructor will not do anything!
        /// </summary>
        public CImgVerify()
        { }
        #endregion

        #region Public Methods
        /// <summary>
        /// The function <c>GetRandomAlphaNumeric</c> will return the string
        /// generated by the <c>RandomNumberGenerator</c> class. This will be used
        /// to make the string value. The function will check whether the randomnly
        /// generated numerics are falling into 32 to 127 for making
        /// it as a character. If the value returned is not in the range
        /// then that we will be used as it is. By default, the randomnly generated number 
        /// array will hold 3 elements.
        /// </summary>
        /// <returns>string value, which is  the randomnly generated alphanumeric value</returns>
        public string GetRandomAlphaNumeric()
        {
            RandomNumberGenerator rm;
            rm = RandomNumberGenerator.Create();

            byte[] data = new byte[4];

            rm.GetNonZeroBytes(data);

            string sRand = "";
            string sTmp = "";

            for (int nCnt = 0; nCnt <= data.Length - 1; nCnt++)
            {
                int nVal = Convert.ToInt32(data.GetValue(nCnt)) % 10;
                //int nVal = Convert.ToInt32(data.GetValue(nCnt));

                if (nVal > 32 && nVal < 127)
                {
                    sTmp = Convert.ToChar(nVal).ToString();
                }
                else
                {
                    sTmp = nVal.ToString();
                }

                sRand += sTmp.ToString();
            }

            return sRand;
        }

        /// <summary>
        /// Ooops!! I'm too tired to make documentation of this. I think, it is 
        /// possible to add more features to this function. 
        /// 
        /// Let me add doc. later after some time!
        /// </summary>
        /// <param name="sTextToImg">The text which has to be generated as a image</param>
        /// <returns></returns>
        public Bitmap GenerateImage(string sTextToImg)
        {
            // Here, i haven't used any try..catch 

            PixelFormat pxImagePattern = PixelFormat.Format32bppArgb;
            Bitmap bmpImage = new Bitmap(1, 1, pxImagePattern);
            Font fntImageFont = new Font("Georgia", 15, FontStyle.Italic | FontStyle.Bold);
            Graphics gdImageGrp = Graphics.FromImage(bmpImage);

            //float iWidth = gdImageGrp.MeasureString(sTextToImg, fntImageFont).Width;
            //float iHeight = gdImageGrp.MeasureString(sTextToImg, fntImageFont).Height;
            int iWidth = 66;
            int iHeight = 22;

            bmpImage = new Bitmap((int)iWidth, (int)iHeight, pxImagePattern);

            gdImageGrp = NoiceGrp(bmpImage);

            gdImageGrp.TextRenderingHint = TextRenderingHint.AntiAlias;

            gdImageGrp.DrawString(sTextToImg, fntImageFont, new SolidBrush(Color.Red), 0, 0);

            bmpImage = NoiceBMP(bmpImage);

            gdImageGrp.Flush();

            return bmpImage;
        }
        #endregion

        private static Graphics NoiceGrp(Bitmap bmp)
        {
            int iWidth = bmp.Width;
            int iHeight = bmp.Height;
            Random rd = new Random(unchecked((int)DateTime.Now.Ticks));
            Graphics grp = Graphics.FromImage(bmp);
            Pen PenLine = new Pen(Brushes.Brown, rd.Next(1, 2));
            grp.Clear(Color.White);
            Point p1 = new Point(rd.Next(iWidth), rd.Next(iHeight));
            Point p2 = new Point(rd.Next(iWidth), rd.Next(iHeight));
            grp.DrawLine(PenLine, p1, p2);
            return grp;
        }

        private static Bitmap NoiceBMP(Bitmap bmp)
        {
            int iWidth = bmp.Width;
            int iHeight = bmp.Height;
            Random rd = new Random(unchecked((int)DateTime.Now.Ticks));
            int imax = rd.Next(30, 100);
            for (int i = 0; i <= imax; i++)
            {
                int RandPixelX = rd.Next(iWidth);
                int RandPixelY = rd.Next(iHeight);
                bmp.SetPixel(RandPixelX, RandPixelY, GetColor(rd.Next(5)));
            }
            return bmp;
        }

        private static Color GetColor(int rnd)
        {
            switch (rnd)
            {
                case 0:
                    return Color.Blue;
                case 1:
                    return Color.Green;
                case 2:
                    return Color.Yellow;
                case 3:
                    return Color.Brown;
                case 4:
                    return Color.Purple;
                default:
                    return Color.Pink;
            }
        }
    }
}